package com.xiaoxu.rental.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * @Title: JwtUtils
 * @Author Mr.Xu
 * @Package com.xiaoxu.rental.util
 * @Date 2024/7/24 20:58
 * @description: JWT工具&配置类
 */
@Component
public class JwtUtils {
    //JWT密钥
    public static final String SECRET_KEY = "XTQ_AI_ZQ";
    //过期时间
    public static final long EXPIRE_TIME = 1000L * 60 * 30;

    /**
     * 创建JWT令牌。
     *
     * 本函数通过接收一个Map对象作为载荷(payload)来生成JWT令牌。载荷中包含了令牌的签发时间、过期时间和生效时间等信息。
     * 使用JWTUtil工具类的createToken方法来实际生成令牌，该方法需要载荷和秘钥作为输入。
     *
     * @param payload 令牌的载荷，包含令牌的相关信息。
     * @return 生成的JWT令牌字符串。
     */
    public static String createToken(Map<String,Object> payload){
        // 获取当前时间
        DateTime now = DateTime.now();
        // 计算令牌的过期时间，EXPIRE_TIME定义了令牌的有效期
        DateTime newTime = new DateTime(now.getTime() + EXPIRE_TIME);

        // 设置Token的签发时间 issued
        payload.put(JWTPayload.ISSUED_AT,now);
        // 设置Token的过期时间
        payload.put(JWTPayload.EXPIRES_AT, newTime);

        // 设置载荷中的生效时间，确保令牌立即生效
        payload.put(JWTPayload.NOT_BEFORE,now);

        // 使用JWTUtil工具类和设定的秘钥生成JWT令牌
        return JWTUtil.createToken(payload,SECRET_KEY.getBytes());
    }


    /**
     * 解析JWT令牌并返回负载。
     *
     * 本函数接收一个JWT令牌字符串作为输入，验证令牌的有效性和过期状态。
     * 如果令牌无效或已过期，将抛出运行时异常。否则，将返回令牌的负载部分。
     *
     * @param token 待解析的JWT令牌字符串。
     * @return 解析后的JWT负载对象。
     * @throws RuntimeException 如果令牌无效或已过期。
     */
    public static JWTPayload parseToken(String token){
        // 解析JWT令牌
        JWT jwt = JWTUtil.parseToken(token);

        // 验证JWT令牌的签名，确保令牌未被篡改
        if (!jwt.setKey(SECRET_KEY.getBytes()).verify()){
            throw  new RuntimeException("token无效");
        }

        // 检查JWT令牌是否过期
        if (!jwt.validate(0)){
             throw  new RuntimeException("token已过期");
        }

        // 返回JWT令牌的负载部分
        return jwt.getPayload();
    }
}
